# -*- coding: UTF-8 -*-
import time
import os
import re
import _thread
import sys
import queue
from tool.handle.Change_Filename.class_define.subprocess import *
from tool.handle.Change_Filename.file_method import Time_cos

debug_mode="1" #print相关 0为输出

from tqdm import tqdm

#异常类：
class MyException(BaseException):
    def __init__(self,message):
        self.message = message
class case_name():
    model_str="Model"
    #机型匹配  非获取得到
    # machine_mode={"聚龙":"Model_JL"}
    #必须获取得到
    name_attr=["currency",'version','value','sn','error_code','after_break','direction']
    #文件名后缀
    file_suffix_attr=['adc0.raw','adc1.raw','cis_bottom.bmp','cis_top.bmp']
    #角度替换
    angle_replace={'0':'A','1':'B','2':'C','3':'D'}
    #当无数据时文件名显示什么
    none_value_result={"currency":"XXX",'version':"0",'value':"0",'sn':"",'error_code':"0",'after_break':'0','direction':'0'}
    #拼接名
    pattern_result_name={"currency":"","version":"Ver","value":"Den","sn":"SN","error_code":"Err","after_break":"LastErr0x",'direction':"Dir"}
    def __init__(self):
        #机器的型号
        self.model_type= ""
        #特殊模式：模式1 无需填写err
        self.mode_run=""
        #样本数据 四个为一捆
        self.name_dic_list={}
        #绝对文件路径
        self.absolute_file_path=""
        #绝对app路径
        self.absolute_app_path=""
        #队列用于监听管道信息
        self.cmdOutQueue = queue.Queue()
        #结果返回 查一个就改一个
        self.run_result_name={}
        self.change_pattern=re.compile('')
        for key in case_name.name_attr:
            self.run_result_name[key]=""



 #监听管道
    def listenStdout(self, hFun):
        while True:
            sys.stdout.flush()
            lineStr = hFun.stdout.readline()
            # print lineStr
            self.cmdOutQueue.put(lineStr)

            if "exit" in lineStr:
                break

    def clearStdout(self, key,times=100):
        #wwm 1.7
        # time.sleep(0.01 * 100)
        time.sleep(0.01)
        str = ""
        while not self.cmdOutQueue.empty():
            str = str + self.cmdOutQueue.get()
        if debug_mode == "0":
            print("{0} output:{1}".format(key,str))
        sys.stdout.flush()  # 刷新缓冲区

    def checkCommand(self, times=100):
        n = 0
        while self.cmdOutQueue.empty():
            time.sleep(0.01)
            n = n + 1
            if n > times:
                break
        str = ""
        while not self.cmdOutQueue.empty():
            str = str + self.cmdOutQueue.get()
        if "OK" in str:
            return True
        else:
            # command_logger.error("recv <="+str)
            return False


#run命令输出结果判定保存
    def checkRunCommand(self):
        # time.sleep(0.5)
        times = 100
        n = 0
        while self.cmdOutQueue.empty():
            time.sleep(0.01)
            n = n + 1
            if n > times:
                break
        str = ""
        str = str + self.cmdOutQueue.get()
        if debug_mode == "0":
             print( str)
        if "OK" not in str:
            print("recv <=" + str)
            print("run command process failed!")


        str = str.lstrip().rstrip()
        index = str.find("command:")
        if index < 0:
            print("recv <=" + str)
            print("command process failed! can NOT find \'command\' in return string")



        str = str[index + 8:]
        retList = str.split()
        retDict = {}
        for key in case_name.name_attr:
            retDict[key]=""
        for element in retList:
            if ":" in element:
                temp = element.split(":")
                retDict[temp[-2]] = temp[-1]

        for key in retDict:
            if key in case_name.name_attr:
                #将结果赋值上  如果无值或者是空格则赋值特定值
                if not retDict[key] or retDict[key].isspace():
                    self.run_result_name[key] = self.none_value_result[key]
                else:
                    self.run_result_name[key] = retDict[key]
        return True
#初始命令
    def start_run_command(self,f):
        #初始需要输入的命令
        f.stdin.write("set --value_mode single\n")
        f.stdin.flush()
        if not self.checkCommand():
            return False
        return True
#跑一次样本
    def run_cash_command(self,f,key):
        bundle_cash = self.name_dic_list[key]
        #TODO  把0换成可以配的格式或许更好些？
        cmd_str = 'load --adc0 %s \n' % bundle_cash[0]
        f.stdin.write(cmd_str)
        f.stdin.flush()
        if not self.checkCommand():
            raise MyException("load fail!!!!!")

        cmd_str = 'load --adc1 %s \n' %bundle_cash[1]
        f.stdin.write(cmd_str)
        f.stdin.flush()
        if not self.checkCommand():
            raise MyException("load fail!!!!!")

        cmd_str = 'load --cis_top %s \n' % bundle_cash[2]
        f.stdin.write(cmd_str)
        f.stdin.flush()
        if not self.checkCommand():
            raise MyException("load fail!!!!!")

        cmd_str = 'load --cis_bottom %s \n' % bundle_cash[3]
        f.stdin.write(cmd_str)
        f.stdin.flush()
        if not self.checkCommand():
            raise MyException("load fail!!!!!")


        cmd_str = 'mark --after_break False \n'
        f.stdin.write(cmd_str)
        f.stdin.flush()
        if not self.checkCommand():
            return False

        cmd_str = 'run \n'
        f.stdin.write(cmd_str)
        f.stdin.flush()
        if not self.checkRunCommand():
            raise MyException("run command fail!!!!!")

#输出结果
        str = "result: "
        for key in self.name_attr:
            temp_str = self.run_result_name[key]
            str = str + (" %s:%s ") % (key, temp_str)


        return True

    # @Time_cos.time_cost_caculate
    def run_change_filename(self,user_database):
        # #匹配模式
        # # receive_command_pattern=re.compile(r'currency:([A-Z]{3})\\s*version:2015  value:100  sn:MY22100140  error_code:[151]  after_break:False')
        # receive_command_pattern_currency=re.compile('currency:([A-Z]{3})\\s*')
        # receive_command_pattern_version=re.compile('version:([0-9]{4})\\s*')
        # receive_command_pattern_value=re.compile('value:([0-9]{0,4})\\s*')
        # receive_command_pattern_sn=re.compile('sn:(.*?)\\s*')
        # receive_command_pattern_error=re.compile('error_code:\\[(.*?)\\]\\s*')
        # receive_command_pattern_break=re.compile('after_break:(False|True)')
        #模式集
        # pattern_index=[receive_command_pattern_currency,receive_command_pattern_version,receive_command_pattern_value,receive_command_pattern_sn,receive_command_pattern_error,receive_command_pattern_break]
        while not self.cmdOutQueue.empty():
            self.cmdOutQueue.get()
        # 跳转当前路径
        progress_bar = tqdm(total=len(self.name_dic_list))
        app_path_exclude = os.path.split(self.absolute_app_path)
        p = Popen(self.absolute_app_path, stdin=PIPE, stdout=PIPE, cwd=app_path_exclude[0])
        total_num=len(self.name_dic_list)
        now_run_num=0
        try:
            _thread.start_new_thread(self.listenStdout, (p,))
            sys.stdout.flush()  # 刷新缓冲区
            for key in self.name_dic_list:
                #命令行输出
                self.clearStdout(key,1)
                #前驱命令
                if not self.start_run_command(p):
                    raise MyException("erro in start_run_command!")
                #样本仿真  获取到固定的值  此时都转化为0
                if not self.run_cash_command(p,key):
                    raise MyException("erro in run_cash_command!")
                #将其转化为写的方案
                if not self.change_name(key):
                    raise MyException("erro in change_name!")
                # sys.stdout.flush()  # 刷新缓冲区
                now_run_num+=1
                user_database.set_progress_bar_value(float("%.2f"%(100.0*now_run_num/total_num)))
                progress_bar.update(1)
            progress_bar.close()
        except MyException as e:
            error_str = "Error ! (%s)"%e
            print(error_str)
            return error_str
        finally:
            time.sleep(1)
            while not self.cmdOutQueue.empty():
                self.cmdOutQueue.get()
            cmd_str = 'bye\n'
            p.stdin.write(cmd_str)
            p.stdin.flush()

        return True



#将其转化为填写格式
    def change_name(self,key):
        #修改格式
        dir_pattern=re.compile(r'/direction-([A-D])/')
        for tmp_key in self.run_result_name:
            # if(tmp_key=='direction'):  #替换为'A' B C D
            #     self.run_result_name[tmp_key]=self.angle_replace[self.run_result_name[tmp_key]]
            #     tmp_group=dir_pattern.search(self.name_dic_list[key][0])
            #     if tmp_group:
            #         self.run_result_name[tmp_key]=tmp_group.group(1)
            #     else:
            #         print("no dir info!")
            #模式一所需
            if(self.mode_run=="no_error" and tmp_key=='error_code'):
                self.run_result_name['error_code'] = "0"
            #app那边传过来的是5  实际表达意思为05
            #如果有冠字号需要加额外下划线
            if(tmp_key=='sn' and self.run_result_name[tmp_key]!="0"):
                self.run_result_name[tmp_key]="_"+self.run_result_name[tmp_key]
            self.run_result_name[tmp_key]=self.pattern_result_name[tmp_key]+self.run_result_name[tmp_key]
        #  tmp.change_pattern = re.compile(r'(.*?_.*?_.*?)_(Err0)_(LastErr0x0)_(Den[0-4])_(Dir0)_(Ver0)_(SN0)')
        #0,1,2,3 ['adc0.raw','adc1.raw','cis_bottom.bmp','cis_top.bmp'] ["currency",'version','value','sn','error_code','after_break','dir']
        #填充
        for key_in, file_list in enumerate(self.name_dic_list[key]):
            file_path,file_name=os.path.split(self.name_dic_list[key][key_in])
            tmp_pattern=re.compile(r'(\d{0,100}_\d{0,100}_\d{0,100})')
            file_front_group=tmp_pattern.match(file_name)
            file_front_name=file_front_group.group(1)

            # file_last_name_pattern = re.compile(r'SN\d{0,10}_(.*?)')
            file_last_name_pattern = re.compile(r'.*_(.*?\.raw|cis_.*?\.bmp)')
            file_last_name=file_last_name_pattern.match(file_name)
            file_last_name=file_last_name.group(1)
            tmp=[]
            # tmp=[file_front_name,self.run_result_name['error_code'],self.run_result_name['after_break'],self.run_result_name['value'],
            #      self.run_result_name['direction'],self.run_result_name['version'],self.run_result_name['sn'],self.file_suffix_attr[key_in]]
            if file_last_name and file_front_name:
                # tmp=[file_front_name,self.model_str ,self.model_type, self.run_result_name["currency"], self.run_result_name['error_code'], self.run_result_name['after_break'], self.run_result_name['value'],
                #  self.run_result_name['direction'], self.run_result_name['version'], self.run_result_name['sn'], self.file_suffix_attr[key_in]]
                tmp = [file_front_name, self.model_str, self.model_type, self.run_result_name["currency"],
                       self.run_result_name['error_code'], self.run_result_name['after_break'],
                       self.run_result_name['value'],
                       self.run_result_name['direction'], self.run_result_name['version'], self.run_result_name['sn'],
                      file_last_name]
            else:
                raise MyException("None_suffix!!")
            file_name="_".join(tmp)
            rename_word=os.path.join(file_path,file_name)
            os.rename(self.name_dic_list[key][key_in],rename_word)
        return True

    # @Time_cos.time_cost_caculate
#传入匹配模式 返回相对应所需要的一捆样本
    def find_sample_file(self):
        count = 0  # 计数器
        all_dic = {}
        for parent, dirnames, filenames in os.walk(self.absolute_file_path):
            if filenames and not dirnames:
                for filename_ext in filenames:
                    tmp_para = filename_ext.split("_")  # 分离
                    if (tmp_para[-1] != "adc0.raw"):  # 只接受adc0的文件
                        continue
                    # file_name,ext=filename_ext.split(".") #分离后缀
                    # ext=ext.lower()          #后缀小写化
                    # if (ext=="raw" and ext=="bmp"):
                    #     pass
                    del tmp_para[-1]  # 删除尾后缀
                    front_filename = "_".join(tmp_para)  # 将文件前名保存
                    # if (self.change_pattern.match(front_filename)):  # 符合需要改名条件的放入
                    adc0_file_name = front_filename + "_adc0.raw"
                    adc1_file_name = front_filename + "_adc1.raw"
                    bottom_file_name = front_filename + "_cis_bottom.bmp"
                    top_file_name = front_filename + "_cis_top.bmp"
                    adc0_file_path = os.path.join(parent, adc0_file_name)
                    adc1_file_path = os.path.join(parent, adc1_file_name)
                    top_file_path = os.path.join(parent, top_file_name)
                    bottom_file_path = os.path.join(parent, bottom_file_name)
                    # print("{0} need change!".format(front_filename))
                    count += 1
                    tmp_dic = {count: [adc0_file_path, adc1_file_path, top_file_path, bottom_file_path]}
                    all_dic.update(tmp_dic)
        self.name_dic_list= all_dic